import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

import 'base_painter.dart';
import 'chart_bean.dart';

/// 柱状图
class ChartHorBarPainter extends BasePainter {
  double _fixedHeight = 0.0, _fixedWidth = 0.0; //宽高
  double value; //当前动画值
  List<ChartBean>? chartBeans;
  late double startX, endX, startY, endY;
  List<double> maxMin = [0, 0]; //存储极值
  Color rectColor; //柱状图默认的颜色
  bool isShowX; //是否显示x轴的文本
  late double rectWidth; //柱状图的宽度
  late double rectHeight; //柱状图的高度
  double fontSize; //刻度文本大小
  Color? fontColor; //文本颜色
  double rectRadius; //矩形的圆角
  //以下的四周圆角只有在 rectRadius 为0的时候才生效
  double rectRadiusTopLeft,
      rectRadiusTopRight,
      rectRadiusBottomLeft,
      rectRadiusBottomRight;
  bool _isAnimationEnd = false;
  bool isCanTouch;
  Color? rectShadowColor; //触摸时显示的阴影颜色
  bool isShowTouchShadow; //触摸时是否显示阴影
  bool isShowTouchValue; //触摸时是否显示值
  Offset? globalPosition; //触摸位置
  Map<Rect, double> rectMap = Map();

  double defaultRectPadding = 2; //默认柱状图的间隔
  double basePadding = 10.w; //默认的边距
  static const Color defaultColor = Colors.deepPurple;
  static const Color defaultRectShadowColor = Colors.white;

  ChartHorBarPainter(
    this.chartBeans,
    this.rectColor, {
    this.value = 1,
    this.isShowX = false,
    this.fontSize = 12,
    this.fontColor,
    this.isCanTouch = false,
    this.isShowTouchShadow = true,
    this.isShowTouchValue = false,
    this.rectShadowColor,
    this.globalPosition,
    this.rectRadius = 0,
    this.rectRadiusTopLeft = 0,
    this.rectRadiusTopRight = 0,
    this.rectRadiusBottomLeft = 0,
    this.rectRadiusBottomRight = 0,
  });

  @override
  void paint(Canvas canvas, Size size) {
    _init(size);

    //重新计算间隔和柱状图高度
    defaultRectPadding = _fixedHeight / chartBeans!.length / 2;
    var maxRectHeight =
        _fixedHeight - (chartBeans!.length - 1) * defaultRectPadding;
    rectHeight = maxRectHeight / chartBeans!.length; //横向柱状图 单个的高度

    _drawX(canvas, size); //x轴刻度
    _drawXLine(canvas, size);
    _drawBar(canvas, size); //柱状图
  }

  @override
  bool shouldRepaint(ChartHorBarPainter oldDelegate) {
    _isAnimationEnd = oldDelegate.value == value;
    return oldDelegate.value != value || isCanTouch;
  }

  /// 初始化
  void _init(Size size) {
    startX = isShowX ? basePadding * 9 : basePadding;
    endX = size.width - basePadding;
    startY = size.height - basePadding;
    endY = basePadding * 2;
    _fixedHeight = startY - endY;
    _fixedWidth = endX - startX;
    maxMin = calculateMaxMin(chartBeans);
  }

  /// x轴刻度值
  void _drawX(Canvas canvas, Size size) {
    if (chartBeans?.isEmpty ?? true) return;

    var style = TextStyle(
      color: fontColor ?? defaultColor,
      fontSize: fontSize,
    );

    List<String> maxMin2 = calculateXMaxMin(chartBeans);
    var mSize = calculateTextSize(maxMin2[0].toString(), style);

    //重新计算startX
    startX = mSize.width > basePadding ? mSize.width : basePadding;
    endX = size.width - startX;
    _fixedWidth = endX - startX;

    //去除所有间隔之后的所有柱状图宽度(最多7个柱状图,6段)
    var maxRectWidth = _fixedWidth - 6 * defaultRectPadding;
    rectWidth = maxRectWidth / 7; //单个柱状图的宽度

    var maxRectHeight =
        _fixedHeight - (chartBeans!.length - 1) * defaultRectPadding;
    rectHeight = maxRectHeight / chartBeans!.length; //横向柱状图 单个的高度

    for (int i = 0; i < chartBeans!.length; i++) {
      double bottom = startY - defaultRectPadding * i - rectHeight * i;
      double top = bottom - rectHeight;
      double y = top + rectHeight / 2;

      TextPainter(
        ellipsis: '.',
        maxLines: 1,
        textAlign: TextAlign.center,
        textDirection: TextDirection.ltr,
        text: TextSpan(
          text: chartBeans![i].x,
          style: style,
        ),
      )
        ..layout(minWidth: mSize.width)
        ..paint(canvas, Offset(basePadding, y - defaultRectPadding / 3));
    }
  }

  /// 绘制X轴 刻度线
  void _drawXLine(Canvas canvas, Size size) {
    if (chartBeans?.isEmpty ?? true) return;

    double y = startY;

    var paint = Paint()
      ..isAntiAlias = true
      ..strokeWidth = 0.5.w
      ..strokeCap = StrokeCap.round
      ..color = const Color(0xff0085F7)
      ..style = PaintingStyle.fill;

    startX = startX + basePadding * 2;

    for (var i = 0; i < 6; i++) {
      double x = (_fixedWidth / 5) * i + startX;
      canvas.drawLine(Offset(x, 0), Offset(x, y), paint);
    }
  }

  /// 柱状图
  void _drawBar(Canvas canvas, Size size) {
    if (chartBeans?.isEmpty ?? true) return;

    var paint = Paint()
      ..isAntiAlias = true
      ..strokeWidth = 5
      ..strokeCap = StrokeCap.round
      ..color = rectColor
      ..style = PaintingStyle.fill;

    if (maxMin[0] <= 0) return;
    //最多只绘制7组数据
    rectMap.clear();
    var length = min(7, chartBeans!.length);

    for (int i = 0; i < length; i++) {
      if (chartBeans![i].color != null) {
        paint.color = chartBeans![i].color!;
      } else {
        paint.color = rectColor;
      }

      double currentWidth =
          startX + chartBeans![i].y / maxMin[0] * _fixedWidth * value;
      double bottom = startY - defaultRectPadding * i - rectHeight * i;
      double top = bottom - rectHeight;
      var rect = Rect.fromLTRB(startX, top, currentWidth, bottom);
      if (rectRadius != 0) {
        canvas.drawRRect(
          RRect.fromRectAndRadius(rect, Radius.circular(rectRadius)),
          paint,
        );
      } else {
        canvas.drawRRect(
          RRect.fromRectAndCorners(
            rect,
            topLeft: Radius.circular(rectRadiusTopLeft),
            topRight: Radius.circular(rectRadiusTopRight),
            bottomLeft: Radius.circular(rectRadiusBottomLeft),
            bottomRight: Radius.circular(rectRadiusBottomRight),
          ),
          paint,
        );
      }
      if (!rectMap.containsKey(rect)) rectMap[rect] = chartBeans![i].y;

      //绘制柱状图右边的文字 值
      TextPainter(
        ellipsis: '.',
        maxLines: 1,
        textAlign: TextAlign.right,
        textDirection: TextDirection.rtl,
        text: TextSpan(
          text: "${chartBeans![i].y}",
          style: TextStyle(color: fontColor, fontSize: fontSize),
        ),
      )
        ..layout(minWidth: rect!.width)
        ..paint(
          canvas,
          Offset(rect!.left, rect!.bottom - defaultRectPadding),
        );
    }
  }
}
